/*******************************************************************************
 * @file Spoon.h
 * Definition of the CSpoon class.
 * 
 * @package Dining.
 * 
 * @author mk
 * @date 03/01/2008 13:50:21
 * @version 0.1
 ******************************************************************************/

#ifndef __SPOON_H_INCLUDED__
#define __SPOON_H_INCLUDED__

#include <boost/thread/mutex.hpp>
#include "Assert.h"

//#define __USE_MUTEX_SPOON__

/** @brief Project related classes are scoped by this namespace. */
namespace Dining
{
	/** @brief Class for defining a spoon which is a mutex. */
	class CSpoonMutex : public boost::mutex
	{
	public:
		/** Default constructor. Disallowing implicit conversion. */
		explicit CSpoonMutex(const unsigned int anId = 0);
		
		/** Destructor. */
		virtual ~CSpoonMutex();
		
		/** Get the id of an instance of this class. */
		const unsigned int GetId() const { return m_Id; }

	private:
		/** Asignment operator made private for disallowing copy assignment. */
		CSpoonMutex& operator= (const CSpoonMutex& /*aSpoon*/);

		/** Copy constructor made private for disallowing copy construction. */
		CSpoonMutex(const CSpoonMutex& /*aSpoon*/);

		const unsigned int m_Id; ///< has an id
	};

	/** @brief Class for defining an unsynced spoon. */
	class CSpoonUnsync
	{ 
	public:
		explicit CSpoonUnsync(const unsigned int anId = 0);
		virtual ~CSpoonUnsync();
		const unsigned int GetId() volatile { return m_Id; }

	private:
		CSpoonUnsync& operator= (const CSpoonUnsync&);
		CSpoonUnsync(const CSpoonUnsync&);
		const unsigned int m_Id;
	};

	/**
	 * @brief Class for defining the sync'd spoon. 
	 *
	 * This is a wrapper for the common "unsynced" spoon class.
	 * Using this class avoids spoon being a mutex.
	 * Instead it wraps a spoon and a responsible mutex.
	 */
	class CSpoonSync
	{
	public:
		explicit CSpoonSync(const unsigned int anId = 0);
		virtual ~CSpoonSync();
		const unsigned int GetId() const
		{
			__ASSERT_POINTER(m_Spoon);
			return m_Spoon->GetId();
		}
		volatile CSpoonUnsync* m_Spoon; ///< has a volatile spoon
	    boost::mutex m_Mutex;	///< has mutex which controls access to the member spoon

	private:
		CSpoonSync& operator= (const CSpoonSync&);
		CSpoonSync(const CSpoonSync&);
	};
#ifdef __USE_MUTEX_SPOON__
	typedef CSpoonMutex CSpoon;
#else
	typedef CSpoonSync CSpoon;
#endif
}

#endif /* __SPOON_H_INCLUDED__ */
